package com.hfi.alibaba.threadlocal;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

/**
 * @author ChangLiang
 * @date 2019/7/1
 */
@Slf4j
public class ThreadLocalTest {
    
    @Test
    public void test() throws InterruptedException {
        Thread t1 = new ProcessThread(new User("Bob", 120));
        Thread t2 = new ProcessThread(new User("Alice", 98));
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        log.info("main thread end");
    }
}

@Data
@AllArgsConstructor
class User{
    String name;
    int level;
}

@Slf4j
class UserContext implements AutoCloseable {

    static final ThreadLocal<User> context = new ThreadLocal<>();

    public UserContext(User user) {
        context.set(user);
    }

    public static User getCurrentUser() {
        return context.get();
    }

    @Override
    public void close() throws Exception {
        log.info(Thread.currentThread().getName()+" close");
        context.remove();
    }

}

class ProcessThread extends Thread{
    User user;

    ProcessThread(User user) {
        super.setName("ProcessThread-"+user.getName());
        this.user = user;
    }

    @Override
    public void run() {
        try (UserContext ctx = new UserContext(user)) {
            // step 1:
            new Greeting().hello();
            // step 2:
            Level.checkLevel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

@Slf4j
class Greeting{
    void hello() {
        User currentUser = UserContext.getCurrentUser();
        log.info("hello, " + currentUser.getName() + "!");
    }
}

@Slf4j
class Level{
    static void checkLevel() {
        User currentUser = UserContext.getCurrentUser();
        if (currentUser.getLevel() > 100) {
            log.info(currentUser.getName() + " is a VIP user");
        } else {
            log.info(currentUser.getName() + " is a registered user");
        }
    }
}
